<template>
  <div ref="flipNode" class="flip down">
    <div ref="frontNode" class="digital front number0"></div>
    <div ref="backNode" class="digital back number1"></div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
  name: "Flop",
  props: ["number"],

  data() {
    return {
      // 正在翻转中
      isFlipping: false,
      // 当前数字
      count: 0,
    };
  },

  mounted() {
    this.handleNumber(this.number, this.number);
  },

  watch: {
    number(old, newVal) {
      this.handleNumber(old, newVal);
    },
  },

  methods: {
    handleNumber(old: number, newVal: number) {
      // 如果处于翻转中，则不执行
      if (this.isFlipping) {
        return false;
      }

      const frontNode = this.$refs["frontNode"] as HTMLElement;
      const backNode = this.$refs["backNode"] as HTMLElement;
      const flip = this.$refs["flipNode"] as HTMLElement;

      // 设置前牌的文字
      frontNode.setAttribute("class", "digital front number" + newVal);
      // 计算后牌文字（越界判断）
      var nextCount = old;
      // 设置后牌的文字
      backNode.setAttribute("class", "digital back number" + nextCount);
      // 添加go，执行翻转动画
      flip.setAttribute("class", "flip down go");
      // 将翻转态设置为true
      this.isFlipping = true;
      // 翻转结束后，恢复状态
      setTimeout(() => {
        // 去掉go
        flip.setAttribute("class", "flip down");
        // 将翻转态设置为false
        this.isFlipping = false;
        // 设置前牌文字为+1后的数字
        frontNode.setAttribute("class", "digital front number" + nextCount);
        // 更新当前文字
        this.count = nextCount;
      }, 1000)
    }
  }
})
</script>

<style lang="scss">
.flip {
  display: inline-block;
  position: relative;
  width: 60px;
  height: 100px;
  margin: 0 5px;
  line-height: 100px;
  border-radius: 10px;
  background: #fff;
  font-size: 66px;
  color: #fff;
  box-shadow: 0 0 6px rgba(0, 0, 0, 0.5);
  text-align: center;
  font-family: "Helvetica Neue";

  & .digital:before,
  & .digital:after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    background: #000;
    overflow: hidden;
  }

  & .digital:before {
    top: 0;
    bottom: 50%;
    border-radius: 10px 10px 0 0;
    border-bottom: solid 1px #666;
  }

  & .digital:after {
    top: 50%;
    bottom: 0;
    border-radius: 0 0 10px 10px;
    line-height: 0;
  }

  // 生成数字对应的类
  @for $i from 0 through 9 {
    & .number#{$i}:before,
    & .number#{$i}:after {
      content: "#{$i}";
    }
  }

  /*向下翻*/
  &.down .front:before {
    z-index: 3;
  }

  &.down .back:after {
    z-index: 2;
    transform-origin: 50% 0%;
    transform: perspective(160px) rotateX(180deg);
  }

  &.down .front:after,
  &.down .back:before {
    z-index: 1;
  }

  /*向上翻*/
  &.up .front:after {
    z-index: 3;
  }

  &.up .back:before {
    z-index: 2;
    transform-origin: 50% 100%;
    transform: perspective(160px) rotateX(-180deg);
  }

  &.up .front:before,
  &.up .back:after {
    z-index: 1;
  }

  &.down.go .front:before {
    transform-origin: 50% 100%;
    animation: frontFlipDown 0.6s ease-in-out both;
    box-shadow: 0 -2px 6px rgba(255, 255, 255, 0.3);
    backface-visibility: hidden;
  }

  &.down.go .back:after {
    animation: backFlipDown 0.6s ease-in-out both;
  }

  @keyframes frontFlipDown {
    0% {
      transform: perspective(160px) rotateX(0deg);
    }

    100% {
      transform: perspective(160px) rotateX(-180deg);
    }
  }

  @keyframes backFlipDown {
    0% {
      transform: perspective(160px) rotateX(180deg);
    }

    100% {
      transform: perspective(160px) rotateX(0deg);
    }
  }

  &.up.go .front:after {
    transform-origin: 50% 0;
    animation: frontFlipUp 0.6s ease-in-out both;
    box-shadow: 0 2px 6px rgba(255, 255, 255, 0.3);
    backface-visibility: hidden;
  }

  &.up.go .back:before {
    animation: backFlipUp 0.6s ease-in-out both;
  }

  @keyframes frontFlipUp {
    0% {
      transform: perspective(160px) rotateX(0deg);
    }

    100% {
      transform: perspective(160px) rotateX(180deg);
    }
  }

  @keyframes backFlipUp {
    0% {
      transform: perspective(160px) rotateX(-180deg);
    }

    100% {
      transform: perspective(160px) rotateX(0deg);
    }
  }
}
</style>